`timescale 1ns/1ps
`include "Func.v"
`define E203_XLEN 32
`define E203_ADDR_SIZE 32
module Top(
  input wire clk, 
// input wire clk_in1_p,
// input wire clk_in1_n,
   input wire rst_n,

  input                         nice_clk            ,
   input                         nice_rst_n	        ,
   output                        nice_active	        ,
   output                        nice_mem_holdup     ,//avoid memory read or write by other devices
   //    output                      nice_rsp_err_irq,
   // Control cmd_req
   input                         nice_req_valid       ,//E203 send a nice request
   output                        nice_req_ready       ,//nice can receive request
   input  [`E203_XLEN-1:0]       nice_req_inst        ,//custom instruction
   input  [`E203_XLEN-1:0]       nice_req_rs1         ,//the register 1
   input  [`E203_XLEN-1:0]       nice_req_rs2         ,//the register 2
   // Control cmd_rsp	
   output                        nice_rsp_valid       ,//nice send response
   input                         nice_rsp_ready       ,//e203 can receive response
   //NICE接口信号中，有两个数据传输信号： nice_rsp_rdat和nice_icb_cmd_wdata。这两个信号对应不同的寄存器。
   output [`E203_XLEN-1:0]       nice_rsp_rdat        ,//compute result ,nice_rsp_rdat对应每一行的相加结果，且每次ROWSUM计算完成后均通过nice_rsp_rdat上传结果，这是通过RD寄存器，不会涉及memory的操作
   output                        nice_rsp_err         ,//nice has error
   // Memory lsu_req	
   output                        nice_icb_cmd_valid   ,//nice send a memory request
   input                         nice_icb_cmd_ready   ,//e203 can receive memory request
   output [`E203_ADDR_SIZE-1:0]  nice_icb_cmd_addr    ,//memory request address
   output                        nice_icb_cmd_read    ,//0:write 1:read
   output [`E203_XLEN-1:0]       nice_icb_cmd_wdata   ,//write data request，是NICE与memory之间传输的数据，首先读取RS寄存器中存储的内存地址，随后完成对应内存地址的数据读写
   //    output [`E203_XLEN_MW-1:0]  nice_icb_cmd_wmask   ,
   output [1:0]                  nice_icb_cmd_size    ,//00:byte 01:half-word 10:word
   // Memory lsu_rsp	
   input                         nice_icb_rsp_valid   ,//e203 send memory response
   output                        nice_icb_rsp_ready   ,//nice can receive memory
   input  [`E203_XLEN-1:0]       nice_icb_rsp_rdata   ,//the data read from memory
   input                         nice_icb_rsp_err     //error during memory access

);

// wire clk;
// clk_wiz_0 u_clk_wiz_0
//    (
//     // Clock out ports
//     .clk_out1(clk),     // output clk_out1
//     // Status and control signals
//     .resetn(rst_n), // input resetn
//    // Clock in ports
//     .clk_in1_p(clk_in1_p),    // input clk_in1_p
//     .clk_in1_n(clk_in1_n));    // input clk_in1_n

parameter RAM1_DEPTH = 512;
parameter RAM2_DEPTH = 512;
parameter RAM3_DEPTH = 512;
parameter block_size = 32;
parameter R1_Block_num =  RAM1_DEPTH/block_size;
parameter R2_Block_num =  RAM2_DEPTH/block_size;
parameter R3_Block_num =  RAM3_DEPTH/block_size;

//  parameter R1_Sel = `R1_KeyGen512_Sel  ;
//  parameter R2_Sel = `R2_KeyGen512_Sel  ;


wire R1_read,R1_write,R2_read,R2_write;
wire [8: 0] R1_trans_addra;
wire [8: 0] R2_trans_addra;
wire R1_trans_ena,R1_trans_wea,R2_trans_ena,R2_trans_wea;
wire  [95:0] R1_trans_Dina, R2_trans_Dina;
wire [95:0] R1_DoutA,R2_DoutA;

//******************* fetch **************************//


wire inst_done;
wire sha_inst_done;
wire [21:0] inst;

wire Start_Decode;

wire Inst_Sel;
wire Poly_Enable = Inst_Sel;
wire enable_sha;

wire [3:0]sha_rs1,sha_rs2,sha_dst;

IFU u_IFU(
    // System	
    .nice_clk              (clk),
    .nice_rst_n	         (nice_rst_n),
    .nice_active	         (nice_active),
    .nice_mem_holdup       (nice_mem_holdup),//avoid memory read or write by other devices
//    .nice_rsp_err_irq      (nice_rsp_err_irq),

    .nice_req_valid        (nice_req_valid),//E203 send a nice request
    .nice_req_ready        (nice_req_ready),//nice can receive request
    .nice_req_inst         (nice_req_inst),//custom instruction
    .nice_req_rs1          (nice_req_rs1),//the register 1
    .nice_req_rs2          (nice_req_rs2),//the register 2

    .nice_rsp_valid        (nice_rsp_valid),//nice send response
    .nice_rsp_ready        (nice_rsp_ready),//e203 can receive response

    .nice_rsp_rdat         (nice_rsp_rdat),//compute result ,nice_rsp_rdat对应每一行的相加结果，且每次ROWSUM计算完成后均通过nice_rsp_rdat上传结果，这是通过RD寄存器，不会涉及memory的操作
    .nice_rsp_err          (nice_rsp_err),//nice has error

    .nice_icb_cmd_valid    (nice_icb_cmd_valid),//nice send a memory request
    .nice_icb_cmd_ready    (nice_icb_cmd_ready),//e203 can receive memory request
    .nice_icb_cmd_addr     (nice_icb_cmd_addr),//memory request address
    .nice_icb_cmd_read     (nice_icb_cmd_read),//0:write 1:read
    .nice_icb_cmd_wdata    (nice_icb_cmd_wdata),//write data request，是NICE与memory之间传输的数据，首先读取RS寄存器中存储的内存地址，随后完成对应内存地址的数据读写
//    .nice_icb_cmd_wmask    (nice_icb_cmd_wmask),
    .nice_icb_cmd_size     (nice_icb_cmd_size),//00:byte 01:half-word 10:word

    .nice_icb_rsp_valid    (nice_icb_rsp_valid),//e203 send memory response
    .nice_icb_rsp_ready    (nice_icb_rsp_ready),//nice can receive memory
    .nice_icb_rsp_rdata    (nice_icb_rsp_rdata),//the data read from memory
    .nice_icb_rsp_err      (nice_icb_rsp_err),//error during memory access

    //Decoder Interface
    .inst                  (inst),
//    .sha_inst              (sha_inst),
    .Start_Decode          (Start_Decode),
//    .sha_Start_Decode      (sha_Start_Decode),

    .R1_read               (R1_read),
    .R1_write              (R1_write),
    .R1_trans_addra        (R1_trans_addra),
    .R1_trans_ena          (R1_trans_ena),
    .R1_trans_wea          (R1_trans_wea),
    .R1_trans_Dina         (R1_trans_Dina),
    .R1_DoutA              (R1_DoutA),

    .R2_read               (R2_read),
    .R2_write              (R2_write),
    .R2_trans_addra        (R2_trans_addra),
    .R2_trans_ena          (R2_trans_ena),
    .R2_trans_wea          (R2_trans_wea),
    .R2_trans_Dina         (R2_trans_Dina),
    .R2_DoutA              (R2_DoutA),

    .SHA3_busy            (enable_sha),
    .sha_dst              (sha_dst),
    .Poly_busy            (Poly_Enable)

);

//******************************************************//


//************************** Decoder *******************************//

wire [5:0] func;
wire Poly_Start;

wire [2:0]RAM_CTR;

wire [5:0] sha_func;
wire sha_Inst_Sel;
wire [2:0]sha_RAM_CTR;


wire [$clog2(R1_Block_num)-1:0]R1_AddrAH,R1_AddrBH;
wire [$clog2(R2_Block_num)-1:0]R2_AddrAH,R2_AddrBH;
wire [$clog2(R3_Block_num)-1:0]R3_AddrAH,R3_AddrBH;
Kyber_Decoder theDecoder(
   .clk(clk),
   .rst_n(rst_n),
   .Start_Decode(Start_Decode),
   .inst(inst),

   .func(func),
   .Poly_Start(Poly_Start),
   .RAM_CTR(RAM_CTR),

   .R1_AddrAH(R1_AddrAH),
   .R1_AddrBH(R1_AddrBH),
   .R2_AddrAH(R2_AddrAH),
   .R2_AddrBH(R2_AddrBH),
   .R3_AddrAH(R3_AddrAH),
   .R3_AddrBH(R3_AddrBH),
   .Inst_Sel(Inst_Sel),

   .sha_func(sha_func),
   .sha_RAM_CTR(sha_RAM_CTR),
   .sha_rs1(sha_rs1),
   .sha_rs2(sha_rs2),
   .sha_dst(sha_dst),
   .sha_Inst_Sel(sha_Inst_Sel),                      
   .sha_inst_done(sha_inst_done),
   .inst_done(inst_done)

);

//*****************************************************************//
   wire [95:0] R1_DoutB;
   wire [95:0] R2_DoutB;
   wire [95:0] R3_DoutA,R3_DoutB;

//******************************* sha3 *************************************//读可以是RAM1 or RAM2，但只往RAM1里面写
   
   wire [5:0]  model;
   wire [95:0] data_in_sha;
   wire [3:0]  open_addr0,open_addr1,result_addr;
   wire [8:0]  addr0,addr1,addr2,addr3;
   wire [95:0] data_out_a_sha,data_out_b_sha;
   wire [95:0] r1_dina_sha,r1_dinb_sha,r2_dina_sha,r2_dinb_sha;
   // wire read_req_sha;
   wire valid_o_sha,valid_o_rej,valid_o_bin;
   wire done_sha;
   wire flag_sha;
   wire r1_ena_sha,r1_enb_sha,r1_wea_sha,r1_web_sha;
   wire r2_ena_sha,r2_enb_sha,r2_wea_sha,r2_web_sha;
   wire [8:0]  r1_addra_sha,r1_addrb_sha,r2_addra_sha,r2_addrb_sha;

   wire     read_req_sha3;   
   wire     ram_read_busy,ram_write_busy;

   assign   enable_sha = ~sha_Inst_Sel && sha_func != 6'b111111;

   assign   model = sha_func;

   assign   data_in_sha = enable_sha ? flag_sha ? sha_RAM_CTR[1] ? R2_DoutB : R1_DoutB //rs2
                                                : sha_RAM_CTR[2] ? R2_DoutA : R1_DoutA //rs1
                                                : 96'b0; 
   
   assign   open_addr0 =  enable_sha ? sha_rs1 : 4'b0;
   assign   open_addr1 =  enable_sha ? sha_rs2 : 4'b0;
   assign   result_addr=  enable_sha ? sha_dst : 4'b0;

   //SHA3 RAM CTRL
   assign   r1_ena_sha = enable_sha ;
   assign   r1_enb_sha = enable_sha ;
   assign   r1_wea_sha = sha_RAM_CTR[0] ? 1'b0 : (enable_sha ? valid_o_sha : 1'b0);
   assign   r1_web_sha = sha_RAM_CTR[0] ? 1'b0 : (enable_sha ? valid_o_sha && !valid_o_rej : 1'b0);

   assign   r2_ena_sha = enable_sha ;
   assign   r2_enb_sha = enable_sha ;
   assign   r2_wea_sha = 1'b0; //理论上一直为0
   assign   r2_web_sha = 1'b0; //理论上一直为0

   assign   r1_dina_sha = sha_RAM_CTR[0] ? 96'b0 : data_out_a_sha;
   assign   r1_dinb_sha = sha_RAM_CTR[0] ? 96'b0 : data_out_b_sha;
   assign   r2_dina_sha = 96'b0; //理论上一直为0
   assign   r2_dinb_sha = 96'b0; //理论上一直为0

   assign   r1_addra_sha = r1_wea_sha ? sha_RAM_CTR[0] ? 9'b0 : addr2
                                      : flag_sha ? sha_RAM_CTR[1] ? 9'b0 : addr1
                                                 : sha_RAM_CTR[2] ? 9'b0 : addr0;
   
   assign   r1_addrb_sha = r1_web_sha ? sha_RAM_CTR[0] ? 9'b0 : addr3
                                      : flag_sha ? sha_RAM_CTR[1] ? 9'b0 : addr1
                                                 : sha_RAM_CTR[2] ? 9'b0 : addr0;

   assign   r2_addra_sha =  flag_sha ? sha_RAM_CTR[1] ? addr1 : 9'b0
                                     : sha_RAM_CTR[2] ? addr0 : 9'b0;

   assign   r2_addrb_sha =  flag_sha ? sha_RAM_CTR[1] ? addr1 : 9'b0
                                     : sha_RAM_CTR[2] ? addr0 : 9'b0;

   
   sha3_wrap   sha3_wrap(
                           .clk(clk),
                           .rst_n(rst_n),
                           .enable(enable_sha),
                           .model(model),

                           .ram_read_busy(ram_read_busy),
                           .ram_write_busy(ram_write_busy),
                           .read_req_sha3(read_req_sha3),

                           .data_in(data_in_sha),
                           .open_addr0(open_addr0),
                           .open_addr1(open_addr1),
                           .result_addr(result_addr),
                           .addr0(addr0),
                           .addr1(addr1),
                           .addr2(addr2),
                           .addr3(addr3),
                           .data_out_a(data_out_a_sha),
                           .data_out_b(data_out_b_sha),
                           // .read_req(read_req),
                           .valid_o(valid_o_sha),
                           .valid_o_rej(valid_o_rej),
                           .valid_o_bin(valid_o_bin),
                           .done(done_sha),
                           .flag(flag_sha));

//*********************************************************************//

 //*************** 多项式乘法器 *****************************//
 wire [$clog2(block_size)-1:0] Poly_R3_AddrAL , Poly_R3_AddrBL;
 wire [$clog2(block_size)-1:0] Poly_R2_AddrAL , Poly_R2_AddrBL;
 wire Poly_R3_ena,Poly_R3_enb,Poly_R2_ena,Poly_R2_enb;
 wire Poly_R3_wea,Poly_R3_web,Poly_R2_wea,Poly_R2_web;
 wire [95:0] Poly_R2_DinA,Poly_R2_DinB;
 wire [95:0] Poly_R3_DinA,Poly_R3_DinB;
 wire Poly_Finish;


 wire InFuncPrintRAM;


 wire Poly_R1_request_a_ntt,Poly_R1_request_b_ntt,Poly_R1_request_b_pwm1,Poly_R1_request_b_polyadd,Poly_R1_request_a_encode,Poly_R1_request_b_encode; //RAM1访问标志
 wire [95:0] R2_DoutA_Poly,R2_DoutB_Poly,R3_DoutA_Poly,R3_DoutB_Poly;


 wire [2:0] NTT_floor;
 wire NTT_busy;

 polyminalMultiplier #(.latency(6))
    thepolyminalMultiplier(
        .clk(clk),.rst_n(rst_n),.Start(Poly_Start),.Finish(Poly_Finish),
        .func(func),.RAM_CTR(RAM_CTR),
        .R2_ena(Poly_R3_ena),.R2_enb(Poly_R3_enb),.R1_ena(Poly_R2_ena),.R1_enb(Poly_R2_enb),
        .R2_wea(Poly_R3_wea),.R2_web(Poly_R3_web),.R1_wea(Poly_R2_wea),.R1_web(Poly_R2_web),
        .R2_DinA(Poly_R3_DinA)   ,.R2_DinB(Poly_R3_DinB),   .R1_DinA(Poly_R2_DinA)   ,.R1_DinB(Poly_R2_DinB)   ,        
        .R2_DoutA(R3_DoutA_Poly) ,.R2_DoutB(R3_DoutB_Poly), .R1_DoutA(R2_DoutA_Poly) ,.R1_DoutB(R2_DoutB_Poly) ,
        .R2_AddrAL(Poly_R3_AddrAL),.R2_AddrBL(Poly_R3_AddrBL),.R1_AddrAL(Poly_R2_AddrAL),.R1_AddrBL(Poly_R2_AddrBL),
//        .Compare_cnt_fresh(Compare_cnt_fresh),.Compare_cnt(Compare_cnt),

        //debug  信号
        .NTT_floor(NTT_floor),
        .NTT_busy(NTT_busy),
        .InFuncPrintRAM(InFuncPrintRAM)
        
        );

        assign inst_done = Poly_Finish;
        assign sha_inst_done = done_sha ;
        assign ram_read_busy  = Poly_R1_request_a_ntt | Poly_R1_request_a_encode | Poly_R1_request_b_ntt | Poly_R1_request_b_encode;
        assign ram_write_busy = Poly_R1_request_a_ntt | Poly_R1_request_a_encode | Poly_R1_request_b_ntt | Poly_R1_request_b_polyadd |  Poly_R1_request_b_encode | Poly_R1_request_b_pwm1;

 //RAM1请求信号
 assign Poly_R1_request_a_ntt       = (func == `NTT & (NTT_floor == 0) & NTT_busy & ~RAM_CTR[1]) ; //第一轮NTT取RAM1
 assign Poly_R1_request_a_encode    = (func == `Encode_ADD & Poly_Enable); //Encode_ADD要用到rs1

 assign Poly_R1_request_b_ntt       = (func == `NTT & (NTT_floor == 0) & NTT_busy & ~RAM_CTR[1]) ; //第一轮NTT取RAM1
 assign Poly_R1_request_b_pwm1      = (func == `PWM1 & Poly_Enable); //PWM1要用到RAM1_B
 assign Poly_R1_request_b_polyadd   = (func == `PolyAdd & (RAM_CTR == 3'b011 | RAM_CTR == 3'b100) & Poly_Enable) ; //PolyADD 100
 assign Poly_R1_request_b_encode    = (func == `Encode_ADD & Poly_Enable) ; //Encode_ADD要用到m 固定14位置
 
 assign R2_DoutA_Poly = (Poly_R1_request_a_ntt & ~RAM_CTR[0]) ? R1_DoutA :
                        R2_DoutA;
 assign R2_DoutB_Poly = (Poly_R1_request_b_ntt & ~RAM_CTR[0]) | (Poly_R1_request_b_pwm1 & ~RAM_CTR[0]) | (Poly_R1_request_b_polyadd & RAM_CTR[1]) | (Poly_R1_request_b_encode) ? R1_DoutB :
                        R2_DoutB;
 assign R3_DoutA_Poly = (Poly_R1_request_a_ntt & RAM_CTR[0]) | (Poly_R1_request_a_encode) ? R1_DoutA : 
                        R3_DoutA;
 assign R3_DoutB_Poly = (Poly_R1_request_b_ntt & RAM_CTR[0]) | (Poly_R1_request_b_pwm1 & RAM_CTR[0]) | (Poly_R1_request_b_polyadd & ~RAM_CTR[1]) ? R1_DoutB : 
                        R3_DoutB;
//*****************************************************************//



//********************  RAM1 ************************************//
wire R1_trans = R1_write | R1_read;
wire R2_trans = R2_write | R2_read;


wire [$clog2(block_size)-1:0]R1_AddrAL,R1_AddrBL,R2_AddrAL,R2_AddrBL;
wire [$clog2(RAM1_DEPTH)-1:0]R1_AddrA,R1_AddrB;
wire [$clog2(RAM2_DEPTH)-1:0]R2_AddrA,R2_AddrB;
wire R1_ena,R1_enb,R2_ena,R2_enb;
wire R1_wea,R1_web,R2_wea,R2_web;
wire [95:0] R1_DinA;
wire [95:0] R1_DinB;

wire [95:0] R2_DinA;
wire [95:0] R2_DinB;

assign R1_AddrA = R1_trans ?  R1_trans_addra : 
                              (Poly_R1_request_a_ntt & RAM_CTR[0]) | Poly_R1_request_a_encode ? {R1_AddrAH,Poly_R3_AddrAL} : 
                              (Poly_R1_request_a_ntt & ~RAM_CTR[0]) ? {R1_AddrAH,Poly_R2_AddrAL} :
                              r1_addra_sha;
assign R1_AddrB = (Poly_R1_request_b_ntt & RAM_CTR[0])  | (Poly_R1_request_b_polyadd & ~RAM_CTR[1]) ? {R1_AddrBH,Poly_R3_AddrBL} : 
                  (Poly_R1_request_b_ntt & ~RAM_CTR[0]) | (Poly_R1_request_b_polyadd & RAM_CTR[1]) | Poly_R1_request_b_pwm1 | Poly_R1_request_b_encode ? {R1_AddrBH,Poly_R2_AddrBL} :
                  r1_addrb_sha;
assign R1_ena =   R1_trans ?  R1_trans_ena : 
                              (Poly_R1_request_a_ntt & RAM_CTR[0]) ? Poly_R2_ena :
                              (Poly_R1_request_a_ntt & ~RAM_CTR[0]) | Poly_R1_request_a_encode ? Poly_R3_ena :
                              r1_ena_sha;
assign R1_enb =   (Poly_R1_request_a_ntt & RAM_CTR[0])  | (Poly_R1_request_b_polyadd & ~RAM_CTR[1]) ? Poly_R3_enb : 
                  (Poly_R1_request_a_ntt & ~RAM_CTR[0]) | Poly_R1_request_b_pwm1 | (Poly_R1_request_b_polyadd & RAM_CTR[1]) | Poly_R1_request_b_encode ? Poly_R2_enb :
                  r1_enb_sha;
assign R1_wea =   R1_trans ?  R1_trans_wea : 
                              Poly_R1_request_a_ntt | Poly_R1_request_a_encode ? 0 : 
                              r1_wea_sha; //Poly访问RAM1只有读
assign R1_web =   Poly_R1_request_b_ntt | Poly_R1_request_b_pwm1 | Poly_R1_request_b_polyadd |  Poly_R1_request_b_encode ? 0 : 
                  r1_web_sha;

assign R1_DinA = R1_trans? R1_trans_Dina: r1_dina_sha; //理论上Poly不会往RAM1里面写
assign R1_DinB = r1_dinb_sha;

// assign R1_AddrAL = RAM_CTR[0] ? Poly_R1_AddrAL : Poly_R2_AddrAL;
// assign R1_AddrBL = RAM_CTR[0] ? Poly_R1_AddrBL : Poly_R2_AddrBL;

// DPRAM_debug #(.WIDTH (96) , .DEPTH (512),.Sel(R1_Sel)) RAM1(
//    .clk(clk),
//    .en_a(R1_ena),.en_b(R1_enb),
//    .we_a(R1_wea),.we_b(R1_web), //1:�?  0: �?
//    .AddrA(R1_AddrA) ,.AddrB(R1_AddrB),
//    .DinA(R1_DinA)  , .DinB(R1_DinB),
//    .DoutA(R1_DoutA) , .DoutB(R1_DoutB)
//    // .PrintRAM_Start(Print_RAM_Start),
//    // .InFuncPrintRAM(InFuncPrintRAM)
// );

RAM1 u_RAM1( 
	.ena(R1_ena),
	.enb(R1_enb),
	.clka(clk), 
	.addra(R1_AddrA), 
	.dina(R1_DinA), 
	.douta(R1_DoutA), 
	.clkb(clk), 
	.addrb(R1_AddrB), 
	.dinb(R1_DinB), 
	.doutb(R1_DoutB),
	.wea(R1_wea),
	.web(R1_web)
);


//////////////////////////////////////RAM2/////////////////////////////////////////
assign R2_ena = R2_trans ? R2_trans_ena: 
                           Poly_Enable ? Poly_R2_ena : 
                           r2_ena_sha;
assign R2_enb = Poly_Enable ? Poly_R2_enb : 
                              r2_enb_sha;
assign R2_wea = R2_trans ? R2_trans_wea:
                           Poly_Enable ? Poly_R2_wea : 
                           r2_wea_sha;
assign R2_web = Poly_Enable ? Poly_R2_web : 
                              r2_web_sha;

assign R2_AddrA = R2_trans ?  R2_trans_addra: 
                              Poly_Enable ? {R2_AddrAH,Poly_R2_AddrAL} : 
                              r2_addra_sha;
assign R2_AddrB = Poly_Enable ?  {R2_AddrBH,Poly_R2_AddrBL} : 
                                 r2_addrb_sha;

assign R2_DinA = R2_trans ? R2_trans_Dina: Poly_R2_DinA;
assign R2_DinB = Poly_R2_DinB;
// DPRAM_debug #(.WIDTH (96) , .DEPTH (512),.Sel(R2_Sel)) RAM2(
//    .clk(clk),
//    .en_a(R2_ena),.en_b(R2_enb),
//    .we_a(R2_wea),.we_b(R2_web), //2:�?  0: �?
//    .AddrA(R2_AddrA) ,.AddrB(R2_AddrB),
//    .DinA(R2_DinA)  , .DinB(R2_DinB),
//    .DoutA(R2_DoutA) , .DoutB(R2_DoutB)
//    // .PrintRAM_Start(Print_RAM_Start),
//    // .InFuncPrintRAM(InFuncPrintRAM)
// );


RAM2  u_RAM2( 
	.ena(R2_ena),
	.enb(R2_enb),
	.clka(clk), 
	.addra(R2_AddrA), 
	.dina(R2_DinA), 
	.douta(R2_DoutA), 
	.clkb(clk), 
	.addrb(R2_AddrB), 
	.dinb(R2_DinB), 
	.doutb(R2_DoutB),
	.wea(R2_wea),
	.web(R2_web)
);

//////////////////////////////////////RAM3/////////////////////////////////////////
wire R3_ena,R3_enb;
wire R3_wea,R3_web;
wire [$clog2(block_size)-1:0]R3_AddrAL,R3_AddrBL;
wire [$clog2(RAM3_DEPTH)-1:0]R3_AddrA,R3_AddrB;

assign R3_ena = Poly_R3_ena;
assign R3_enb = Poly_R3_enb;
assign R3_wea = Poly_R3_wea;
assign R3_web = Poly_R3_web;

assign R3_AddrA = {R3_AddrAH,Poly_R3_AddrAL};
assign R3_AddrB = {R3_AddrBH,Poly_R3_AddrBL};

wire [95:0] R3_DinA = Poly_R3_DinA;
wire [95:0] R3_DinB = Poly_R3_DinB;


RAM3 u_RAM3 (
  .clka(clk),    // input wire clka
  .ena(R3_ena),      // input wire ena
  .wea(R3_wea),      // input wire [0 : 0] wea
  .addra(R3_AddrA),  // input wire [7 : 0] addra
  .dina(R3_DinA),    // input wire [95 : 0] dina
  .douta(R3_DoutA),  // output wire [95 : 0] douta
  .clkb(clk),    // input wire clkb
  .enb(R3_enb),      // input wire enb
  .web(R3_web),      // input wire [0 : 0] web
  .addrb(R3_AddrB),  // input wire [7 : 0] addrb
  .dinb(R3_DinB),    // input wire [95 : 0] dinb
  .doutb(R3_DoutB)  // output wire [95 : 0] doutb
);
//************** debug signal ****************//
// always@(posedge clk)
//    begin
//       if(inst_done) Print_RAM_Start <=1'b1;
//       else Print_RAM_Start<=1'b0;
//    end


// integer Keygen512_inst;
// integer Enc512_inst;
// integer Dec512_inst;
// integer Keygen768_inst;
// integer Enc768_inst;
// integer Dec768_inst;
// integer Keygen1024_inst;
// integer Enc1024_inst;
// integer Dec1024_inst;

// always@(posedge clk)
// begin
//    case(mode)
//       `KEM_Kyber512: begin
//          if(keygen_start)   begin Keygen512_inst  = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Keygen512_inst.txt","w");  $display("fuck keygen 512") ;end
//          if(enc_start)      begin Enc512_inst     = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Enc512_inst.txt","w");     $display("fuck end    512") ;end
//          if(dec_start)      begin Dec512_inst     = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Dec512_inst.txt","w");     $display("fuck dec    512") ;end
//       end   
//       `KEM_Kyber768: begin   
//          if(keygen_start)   begin Keygen768_inst  = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Keygen768_inst.txt","w");  $display("fuck keygen 768") ;end
//          if(enc_start)      begin Enc768_inst     = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Enc768_inst.txt","w");     $display("fuck end    768") ;end
//          if(dec_start)      begin Dec768_inst     = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Dec768_inst.txt","w");     $display("fuck dec    768") ;end
//       end  
//       `KEM_Kyber1024: begin  
//          if(keygen_start)  begin Keygen1024_inst  = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Keygen1024_inst.txt","w"); $display("fuck keygen 1024");end
//          if(enc_start)     begin Enc1024_inst     = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Enc1024_inst.txt","w");    $display("fuck end    1024");end
//          if(dec_start)     begin Dec1024_inst     = $fopen("D:/DeskTop/PQC/src/2022_10_11/Hardware/DATA/Dec1024_inst.txt","w");    $display("fuck dec    1024");end
//       end
//    endcase
// end


// always@(posedge clk)
// begin
//    if(inst_done) begin
//       case(mode)
//       `KEM_Kyber512: begin
//          if(keygen) begin $fwrite(Keygen512_inst,"%b\n",inst);  end 
//          if(enc)    begin $fwrite(Enc512_inst,"%b\n",inst);  end 
//          if(dec)    begin $fwrite(Dec512_inst,"%b\n",inst);  end 
//       end
//       `KEM_Kyber768: begin
//          if(keygen) begin $fwrite(Keygen768_inst,"%b\n",inst);  end
//          if(enc)    begin $fwrite(Enc768_inst,"%b\n",inst);  end
//          if(dec)    begin $fwrite(Dec768_inst,"%b\n",inst);  end
//       end
//       `KEM_Kyber1024: begin
//          if(keygen) begin $fwrite(Keygen1024_inst,"%b\n",inst);  end
//          if(enc)    begin $fwrite(Enc1024_inst,"%b\n",inst);  end
//          if(dec)    begin $fwrite(Dec1024_inst,"%b\n",inst);  end
//       end
//       endcase
//    end
// end


endmodule

// module Top_tb();

// reg clk,rst_n;
// reg [2:0] mode;
// reg Keygen_en,Enc_en,Dec_en,Cmd_en;
// wire Success,Fail;

// //RAM传输接口
// reg R1_read,R1_write,R2_read,R2_write;
// reg [8:0]R1_trans_addra,R1_trans_addr_rs,R1_trans_addr_dst;
// reg [8:0]R2_trans_addra,R2_trans_addr_rs,R2_trans_addr_dst;
// wire R1_trans_ena,R2_trans_ena,R1_trans_wea,R2_trans_wea;
// reg [95:0]R1_trans_Dina, R2_trans_Dina;
// wire [95:0]R1_DoutA,R2_DoutA;

// //INST RAM传输接口
// reg [6:0]  inst_addr_write;
// reg [21:0] inst_din_write;
// reg inst_write;


// reg R1_read_start;
// reg R1_write_start;
// reg R2_read_start;
// reg R2_write_start;
// wire R1_read_finish;
// wire R1_write_finish;
// wire R2_read_finish;
// wire R2_write_finish;

// reg ram_busy;

// reg  Inst_trans_start;
// reg  [6:0] Inst_addr_end;
// wire Inst_trans_finish;

// reg [21:0] inst,sha_inst;
// reg Start_Decode,sha_Start_Decode;
// Top thetop(
//    .clk(clk), .rst_n(rst_n),
//    .mode(mode),
//    .Keygen_en(Keygen_en), .Enc_en(Enc_en), .Dec_en(Dec_en),.Cmd_en(Cmd_en),
//    .Success(Success),.Fail(Fail),


//    .R1_read(R1_read),.R1_write(R1_write),.R2_read(R2_read),.R2_write(R2_write),
//    .R1_trans_addra(R1_trans_addra),
//    .R2_trans_addra(R2_trans_addra),
//    .R1_trans_ena(R1_trans_ena),.R2_trans_ena(R2_trans_ena),.R1_trans_wea(R1_trans_wea),.R2_trans_wea(R2_trans_wea),
//    .R1_trans_Dina(R1_trans_Dina), .R2_trans_Dina(R2_trans_Dina),
//    .R1_DoutA(R1_DoutA),.R2_DoutA(R2_DoutA),

//    .inst(inst),
//    .sha_inst(sha_inst),
//    .Start_Decode(Start_Decode),
//    .sha_Start_Decode(sha_Start_Decode),

//    .inst_din_write(inst_din_write), .inst_write(inst_write),.inst_addr_write(inst_addr_write)
// );

// integer R1_Init_file ,R2_Init_file;
// integer output_file2,output_file1;
// parameter R1_Sel = `KEM_R1_Enc512_Sel  ;
// parameter R2_Sel = `KEM_R2_Enc512_Sel  ;

// reg [95:0] R1_mem[0:511];
// reg [95:0] R2_mem[0:511];
// reg [21:0] Inst_mem[0:127];

// initial 
// begin
//     ram_busy = 0;
//     output_file2 = $fopen("./DATA/R2out.txt","w");
//     output_file1 = $fopen("./DATA/R1out.txt","w");
//     clk= 0;
//     rst_n =1;
//     Keygen_en=0;
//     Enc_en=0;
//     Dec_en=0;
//     Cmd_en=0;

//     R1_read_start=0;
//     R1_write_start=0;
//     R2_read_start=0;
//     R2_write_start=0;
//     R1_trans_addra =0;
//     R2_trans_addra =0;
//     R1_trans_Dina  =0;
//     R2_trans_Dina  =0;

//     inst_din_write =0;
//     inst_addr_write =0;
//     inst_write =0;

//     Inst_addr_end = 7'd126;
//     $fwrite(output_file1,"000\n");
//     $fwrite(output_file1,"111\n");
//     $fwrite(output_file1,"222\n");
//     $fwrite(output_file2,"000\n");
//     $fwrite(output_file2,"111\n");
//     $fwrite(output_file2,"222\n");

//     mode =`KEM_Kyber512;
    
//     $readmemb("./DATA/cmd/Dec1024_inst.txt",Inst_mem);
//     case(R1_Sel)
//       `R1_KeyGen512_Sel  : $readmemh("./DATA/Kyber512/RAM1_Keygen_Test.txt",R1_mem);
//       `KEM_R1_Enc512_Sel : $readmemh("C:/Users/96440/Desktop/TEST_PQC/RAM2_Enc_Test.txt",R1_mem);
//       `R1_Dec512_Sel     : $readmemh("./DATA/Kyber512/RAM1_Dec_Test.txt",R1_mem);

//       `R1_KeyGen768_Sel  : $readmemh("./DATA/Kyber768/RAM1_Keygen_Test.txt",R1_mem);
//       `KEM_R1_Enc768_Sel : $readmemh("./DATA/Kyber768/RAM1_Enc_Test.txt",R1_mem);
//       `R1_Dec768_Sel     : $readmemh("./DATA/Kyber768/RAM1_Dec_Test.txt",R1_mem);

//       `R1_KeyGen1024_Sel  : $readmemh("./DATA/Kyber1024/RAM1_Keygen_Test.txt",R1_mem);
//       `KEM_R1_Enc1024_Sel : $readmemh("./DATA/Kyber1024/RAM1_Enc_Test.txt",R1_mem);
//       `R1_Dec1024_Sel     : $readmemh("./DATA/Kyber1024/RAM1_Dec_Test.txt",R1_mem);

//       `R1_Cmd_Sel         : $readmemh("./DATA/cmd/RAM1_cmd_Test.txt",R1_mem);

//       `PKE_R1_Enc512_Sel  : $readmemh("./DATA/Kyber512/PKE_RAM1_Enc_Test.txt",R1_mem);
//       `PKE_R1_Enc768_Sel  : $readmemh("./DATA/Kyber768/PKE_RAM1_Enc_Test.txt",R1_mem);
//       `PKE_R1_Enc1024_Sel :  $readmemh("./DATA/Kyber1024/PKE_RAM1_Enc_Test.txt",R1_mem);
//     endcase
//     case(R2_Sel)
//       `R2_KeyGen512_Sel  : $readmemh("C:/Users/96440/Desktop/TEST_PQC/RAM2_Keygen_Test.txt",R2_mem);
//       `KEM_R2_Enc512_Sel : $readmemh("C:/Users/96440/Desktop/TEST_PQC/RAM2_Enc_Test.txt",R2_mem);
//       `R2_Dec512_Sel     : $readmemh("./DATA/Kyber512/RAM2_Dec_Test.txt",R2_mem);

//       `R2_KeyGen768_Sel  : $readmemh("./DATA/Kyber768/RAM2_Keygen_Test.txt",R2_mem);
//       `KEM_R2_Enc768_Sel : $readmemh("./DATA/Kyber768/RAM2_Enc_Test.txt",R2_mem);
//       `R2_Dec768_Sel     : $readmemh("./DATA/Kyber768/RAM2_Dec_Test.txt",R2_mem);

//       `R2_KeyGen1024_Sel  : $readmemh("./DATA/Kyber1024/RAM2_Keygen_Test.txt",R2_mem);
//       `KEM_R2_Enc1024_Sel : $readmemh("./DATA/Kyber1024/RAM2_Enc_Test.txt",R2_mem);
//       `R2_Dec1024_Sel     : $readmemh("./DATA/Kyber1024/RAM2_Dec_Test.txt",R2_mem);

//       `R2_Cmd_Sel         : $readmemh("./DATA/cmd/RAM2_cmd_Test.txt",R2_mem);

//       `PKE_R2_Enc512_Sel  : $readmemh("./DATA/Kyber512/PKE_RAM2_Enc_Test.txt",R2_mem);
//       `PKE_R2_Enc768_Sel  : $readmemh("./DATA/Kyber768/PKE_RAM2_Enc_Test.txt",R2_mem);
//       `PKE_R2_Enc1024_Sel : $readmemh("./DATA/Kyber1024/PKE_RAM2_Enc_Test.txt",R2_mem);
       

//     endcase
//    #20    rst_n =0;
//    #10    rst_n =1;

//          // 
//          //
      
//       R1_trans_addr_rs   = 320;    //传输R2数据
//       R1_trans_addr_dst  = 320 + 63;
// #100  R1_write_start =1;
// #20  R1_write_start =0;
// wait(R1_write_finish); 

//  #100     

//       R1_trans_addr_rs   = 32*15;    //传输R2数据
//       R1_trans_addr_dst  = 32*15 + 7;
// #100  R1_write_start =1;
// #20  R1_write_start =0;
// wait(R1_write_finish); 
// //begin $stop; end

// //       R1_trans_addr_rs   = 0;
// //       R1_trans_addr_dst  = 255;
// // #100  R1_write_start =1;
// // #20  R1_write_start =0;
// // wait(R1_write_finish); begin $stop; end //传输R2数据

// // #100  Inst_trans_start =1;
// // #20  Inst_trans_start =0;
// // wait(Inst_trans_finish) begin $stop; end //传输InstRAM数据


// sha_inst     = `void_inst;
// inst = `void_inst;
// Start_Decode = 0;
// #10000 Enc_en =1;  //�?启运�?

//        sha_inst = {3'b000 ,4'd8, 4'd0 ,4'd8,`SHA3_Enable,6'b110000}; //H（m） 256bit
//        inst = `void_inst; //H（m） 256bit
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0;  
//        @(posedge thetop.sha_inst_done)
//        #20

//        sha_inst = {3'b000 ,4'd10, 4'd9 ,4'd10,`SHA3_Enable,6'b110001}; //H（pk）  256bit
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0;  
//        @(posedge thetop.sha_inst_done)
//        #20

//        sha_inst = {3'b000 ,4'd8, 4'd10 ,4'd11,`SHA3_Enable,6'b000010}; //G(m|Hpk) 512bit
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0;  
//        @(posedge thetop.sha_inst_done)
//        #20

//        sha_inst = {3'b000 ,4'd12, 4'd0 ,4'd0,`SHA3_Enable,6'B011000}; //采样r0
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0;  
//        #20
       
//        wait(~thetop.enable_sha);
//        inst = {`R2_TO_R1 ,4'd0, 4'd0 ,4'd0,`Poly_Enable,`NTT}; //NTT r0 RAM2->0
//        Start_Decode = 1;
//        #20 Start_Decode = 0;
//        #20

//        sha_inst = {3'b000 ,4'd12, 4'd0 ,4'd1,`SHA3_Enable,6'B011001}; //采样r1
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
//        @(posedge thetop.sha_inst_done)
//        #20

//        wait(~thetop.enable_sha);
//        wait(~thetop.Poly_Enable);
//        inst = {`R2_TO_R1 ,4'd1, 4'd0 ,4'd1,`Poly_Enable,`NTT}; //NTT r1 RAM2->1
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        sha_inst = {3'b000 ,4'd9 , 4'd0 ,4'd2,`SHA3_Enable,6'B100000}; //采样 AT 00  ρ
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
//        @(posedge thetop.sha_inst_done)
//        #20

//        wait(~thetop.enable_sha);
//        wait(~thetop.Poly_Enable);
//        inst = {3'b100 ,4'd2, 4'd0 ,4'd0,`Poly_Enable,`PWM1};   //A00 r0  PWM1
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20 

//        wait(~thetop.Poly_Enable);
//        inst = {3'b001 ,4'd0, 4'd1 ,4'd2,`Poly_Enable,`PWM2};   //A00 r0  PWM2
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20 

//        sha_inst = {3'b000 ,4'd9 , 4'd0 ,4'd3,`SHA3_Enable,6'B100100}; //采样 AT 01  ρ
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
//        @(posedge thetop.sha_inst_done)
//        #20

//        wait(~thetop.enable_sha);
//        wait(~thetop.Poly_Enable);
//        inst = {3'b100 ,4'd3, 4'd1 ,4'd0,`Poly_Enable,`PWM1};   //A01 r1  PWM1
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20 

//        wait(~thetop.Poly_Enable);
//        inst = {3'b001 ,4'd0, 4'd1 ,4'd3,`Poly_Enable,`PWM2};   //A01 r1  PWM2
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        sha_inst = {3'b000 ,4'd9 , 4'd0 ,4'd4,`SHA3_Enable,6'B100001}; //采样 AT 10  ρ
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
//        @(posedge thetop.sha_inst_done)
//        #20

//        wait(~thetop.enable_sha);
//        wait(~thetop.Poly_Enable);
//        inst = {3'b100 ,4'd4, 4'd0 ,4'd0,`Poly_Enable,`PWM1};   //A10 r0  PWM1
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20 

//        wait(~thetop.Poly_Enable);
//        inst = {3'b001 ,4'd0, 4'd1 ,4'd4,`Poly_Enable,`PWM2};   //A10 r0  PWM2
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        sha_inst = {3'b000 ,4'd9 , 4'd0 ,4'd5,`SHA3_Enable,6'B100101}; //采样 AT 11  ρ
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
//        @(posedge thetop.sha_inst_done)
//        #20

//        wait(~thetop.enable_sha);
//        wait(~thetop.Poly_Enable);
//        inst = {3'b100 ,4'd5, 4'd1 ,4'd0,`Poly_Enable,`PWM1};   //A11 r1  PWM1
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20 

//        wait(~thetop.Poly_Enable);
//        inst = {3'b001 ,4'd0, 4'd1 ,4'd5,`Poly_Enable,`PWM2};   //A11 r1  PWM2
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        sha_inst = {3'b000 ,4'd12, 4'd0 ,4'd6,`SHA3_Enable,6'B010010}; //采样e10
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
// //       @(posedge thetop.sha_inst_done)
//        #20
       
// //       wait(~thetop.enable_sha);
//        wait(~thetop.Poly_Enable);
//        inst = {`R11_TO_R2,4'd3, 4'd2,4'd0,`Poly_Enable,`PolyAdd};  //A01r1 + A00r0 = u[0]
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20
       
//        wait(~thetop.enable_sha);
//        sha_inst = {3'b000 ,4'd12, 4'd0 ,4'd7,`SHA3_Enable,6'B010011}; //采样e11
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
// //       @(posedge thetop.sha_inst_done)
//        #20

//        wait(~thetop.Poly_Enable);
//        inst = {`R11_TO_R2,4'd5, 4'd4,4'd1,`Poly_Enable,`PolyAdd};  //A11r1 + A10r0 = u[1]
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        wait(~thetop.enable_sha);
//        sha_inst = {3'b000 ,4'd12, 4'd0 ,4'd7,`SHA3_Enable,6'B010011}; //采样e2
//        sha_Start_Decode = 1;
//        #20 sha_Start_Decode = 0; 
// //       @(posedge thetop.sha_inst_done)
//        #20

//        wait(~thetop.Poly_Enable);
//        inst = {`R2_TO_R1,4'd0, 4'd0,4'd2,`Poly_Enable,`INTT};  //intt u[0]
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        wait(~thetop.Poly_Enable);
//        inst = {`R2_TO_R1,4'd1, 4'd0,4'd3,`Poly_Enable,`INTT};  //intt u[1]
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        wait(~thetop.Poly_Enable);
//        inst = {3'b100,4'd6, 4'd2,4'd0,`Poly_Enable,`PolyAdd};  //e1[0] + u[0]   RAM1+RAM2 ->RAM3 u0
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

//        wait(~thetop.Poly_Enable);
//        inst = {3'b100,4'd7, 4'd3,4'd1,`Poly_Enable,`PolyAdd};  //e1[1] + u[1]   RAM1+RAM2 ->RAM3 u1
//        Start_Decode = 1;
//        #20 Start_Decode = 0; 
//        #20

// #10000 Enc_en =0;
// #100000 $stop;

// // KEM_Keygen512
// //       R2_trans_addr_rs   = 32*6;
// //       R2_trans_addr_dst  = 32*8 - 1;
// // #100  R2_read_start =1;
// // #120  R2_read_start =0;
// // wait(R2_read_finish) begin #100; $stop; end //传输R2数据

// // // KEM_Keygen768
// //       R2_trans_addr_rs   = 32*7;
// //       R2_trans_addr_dst  = 32*10 - 1;
// // #100  R2_read_start =1;
// // #120  R2_read_start =0;
// // wait(R2_read_finish) begin #100; $stop; end //传输R2数据

// // // KEM_Keygen1024
// //       R2_trans_addr_rs   = 32*7;
// //       R2_trans_addr_dst  = 32*11 - 1;
// // #100  R2_read_start =1;
// // #120  R2_read_start =0;
// // wait(R2_read_finish) begin #100; $stop; end //传输R2数据

// // // PKE_Enc512
// //       R1_trans_addr_rs   = 32*0;
// //       R1_trans_addr_dst  = 32*3 - 1;
// // #100  R1_read_start =1;
// // #120  R1_read_start =0;
// // wait(R1_read_finish) begin #100; $stop; end //传输R2数据

// // // PKE_Enc768
// //       R1_trans_addr_rs   = 32*4;
// //       R1_trans_addr_dst  = 32*8 - 1;
// // #100  R1_read_start =1;
// // #120  R1_read_start =0;
// // wait(R1_read_finish) begin #100; $stop; end //传输R2数据

// // // PKE_Enc1024
// //       R1_trans_addr_rs   = 32*3;
// //       R1_trans_addr_dst  = 32*8 - 1;
// // #100  R1_read_start =1;
// // #120  R1_read_start =0;
// // wait(R1_read_finish) begin #100; $stop; end //传输R2数据

// //       R2_trans_addr_rs   = 32*15 + 4*3;
// //       R2_trans_addr_dst  = 32*15 + 4*3 +3;
// // #100  R2_read_start =1;
// // #20  R2_read_start =0;
// // wait(R2_read_finish) begin #100; $stop; end //�? Key

// //       R2_trans_addr_rs   = 32*15;
// //       R2_trans_addr_dst  = 32*15 +3;
// // #100  R2_read_start =1;
// // #20  R2_read_start =0;
// // wait(R2_read_finish) begin #100; $stop; end //�? M


// // //重复性测�?
// //       R2_trans_addr_rs   = 0;    //传输R2数据
// //       R2_trans_addr_dst  = 511;
// // #100  R2_write_start =1;
// // #120  R2_write_start =0;
// // //wait(R2_write_finish) begin $stop; end

// //       R1_trans_addr_rs   = 0;
// //       R1_trans_addr_dst  = 255;
// // #100  R1_write_start =1;
// // #120  R1_write_start =0;
// // //wait(R1_write_finish) begin $stop; end //传输R2数据

// // #10000 Keygen_en =1;  //�?启运�?
// // ram_busy = 1;
// // #500
// // ram_busy = 0;

// // #10000 Keygen_en =0;
// // #100000 //$stop;

// // //       R2_trans_addr_rs   = 32*15 + 4*3;
// // //       R2_trans_addr_dst  = 32*15 + 4*3 +3;
// // // #100  R2_read_start =1;
// // // #20  R2_read_start =0;
// // // wait(R2_read_finish) begin #100; $stop; end //�? Key

// // // KEM_Keygen1024
// //       R2_trans_addr_rs   = 32*7;
// //       R2_trans_addr_dst  = 32*11 - 1;
// // #100  R2_read_start =1;
// // #120  R2_read_start =0;
// // wait(R2_read_finish) begin #100; $stop; end //传输R2数据



// end


// //************** State ******************//
// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) R1_read<=1'b0;
//    else if(R1_read_start & ~R1_read) R1_read<=1'b1;
//    else if(R1_read_finish & R1_read) R1_read<=1'b0;
// end

// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) R2_read<=1'b0;
//    else if(R2_read_start & ~R1_read) R2_read<=1'b1;
//    else if(R2_read_finish & R2_read) R2_read<=1'b0;
// end

// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) R1_write<=1'b0;
//    else if(R1_write_start & ~R1_write) R1_write<=1'b1;
//    else if(R1_write_finish & R1_write) R1_write<=1'b0;
// end

// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) R2_write<=1'b0;
//    else if(R2_write_start & ~R1_write) R2_write<=1'b1;
//    else if(R2_write_finish & R2_write) R2_write<=1'b0;
// end
// //***********************************************//


// //******************** R1 addr  *********************//
// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) R1_trans_addra <= 8'd0;
//    else if(R1_write_start  & ~R1_write)  R1_trans_addra <= R1_trans_addr_rs;
//    else if(R1_write_finish &  R1_write)  R1_trans_addra <= 8'd0;
//    else if(R1_read_start   & ~R1_read )  R1_trans_addra <= R1_trans_addr_rs;
//    else if(R1_read_finish  &  R1_read )  R1_trans_addra <= 8'd0;
//    else if(R1_read | R1_write)           begin R1_trans_addra <= R1_trans_addra + 1'b1; 
//                                                 //$display("Addr=%x Data=%x",R1_trans_addra,R1_trans_Dina); 
//                                                  end
// end
// //***********************************************//

// //*******************  R2 addr  *********************//
// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) R2_trans_addra <= 8'd0;
//    else if(R2_write_start  & ~R2_write)  R2_trans_addra <= R2_trans_addr_rs;
//    else if(R2_write_finish &  R2_write)  R2_trans_addra <= 8'd0;
//    else if(R2_read_start   & ~R2_read )  R2_trans_addra <= R2_trans_addr_rs;
//    else if(R2_read_finish  &  R2_read )  R2_trans_addra <= 8'd0;
//    else if(R2_read | R2_write)           begin R2_trans_addra <= R2_trans_addra + 1'b1; 
//                                          // $display("Addr=%x Data=%x",R2_trans_addra,R2_trans_Dina);  
//                                           end
// end
// //***********************************************//
// reg [9:0] addr_cnt;
// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) addr_cnt <= 10'd0;
//    if(R1_read | R1_write)           
//       addr_cnt <= addr_cnt + 1'b1; 
// end

// //******************* Din ************************//
// always@(*)
// begin
//    if(R1_write) R1_trans_Dina = R1_mem[addr_cnt];
//    else R1_trans_Dina = 95'd0;
// end

// always@(*)
// begin
//    if(R2_write) R2_trans_Dina = R2_mem[addr_cnt];
//    else R2_trans_Dina = 95'd0;
// end


// //*******************  en we  *********************//
// assign R1_trans_ena = R1_read | R1_write;
// assign R2_trans_ena = R2_read | R2_write;
// assign R1_trans_wea = R1_write;
// assign R2_trans_wea = R2_write;
// //***********************************************//


// //***************** finish *********************//
// assign R1_write_finish = R1_write &(R1_trans_addra == R1_trans_addr_dst);
// assign R1_read_finish  = R1_read  &(R1_trans_addra == R1_trans_addr_dst);
// assign R2_write_finish = R2_write &(R2_trans_addra == R2_trans_addr_dst);
// assign R2_read_finish  = R2_read  &(R2_trans_addra == R2_trans_addr_dst);

// //***********************************************//


// //***************  Inst_ram  *****************//
// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) inst_write <=1'b0;
//    else if(Inst_trans_start  & ~ inst_write) inst_write<=1'b1;
//    else if(Inst_trans_finish &   inst_write) inst_write<=1'b0;
// end

// always@(posedge clk or negedge rst_n)
// begin
//    if(!rst_n) inst_addr_write<=7'd0;
//    else if(Inst_trans_start  & ~ inst_write) inst_addr_write<=7'd0;
//    else if(Inst_trans_finish &   inst_write) inst_addr_write<=7'd0;
//    else if(inst_write) inst_addr_write<=inst_addr_write +1'b1;
// end

// assign Inst_trans_finish = inst_addr_write == Inst_addr_end;

// always@(*)
// begin
//    if(inst_write) inst_din_write = Inst_mem[inst_addr_write];
//    else inst_din_write = 22'd0;
// end

// //**************** debug *****************//

// reg [1:0]R2_read_reg ; //凑时�?
// always@(posedge clk)
// begin
//    R2_read_reg<={R2_read_reg[0],R2_read};
//    if(R2_read_reg[1]) begin
//       $fwrite(output_file2,"%x\n",R2_DoutA);
//       $display("Data=%x",R2_DoutA);
//    end
// end

// reg [1:0]R1_read_reg ; //凑时�?
// always@(posedge clk)
// begin
//    R1_read_reg<={R1_read_reg[0],R1_read};
//    if(R1_read_reg[1]) begin
//       $fwrite(output_file1,"%x\n",R1_DoutA);
//       $display("Data=%x",R1_DoutA);
//    end
// end
// always #5 clk = ~clk;
// endmodule